﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace CommonLib.Pattern.FSM
{
	public interface IState 
	{
		/// <summary>
		/// Identit for State
		/// </summary>
		string Key { get; }
		/// <summary>
		/// update duration between two state 
		/// </summary>
		float UpdateDuration { get; }
		/// <summary>
		/// Controller of States
		/// </summary>
		IFSM Machine { get; }
		/// <summary>
		/// 所有状态过渡类的集合
		/// </summary>
		List<ITransition> Transitions { get; }
		//Dictionary<string, ITransition> Transitions { get; }
		void EnterState(IState _preState);
		void ExitState(IState _nextState);
		void UpdateState(float _deltaTime);

		void AddTransition(ITransition _transition);
		void SetMachine(IFSM _machine);
	}

	public class FSMStateBase : IState
	{
		public string Key => stateKey;

		public float UpdateDuration => duration;

		public IFSM Machine => machine;

		public List<ITransition> Transitions => transitions;

		public void AddTransition(ITransition _transition)
		{
			if (null != Transitions.Find(x => x.Key == _transition.Key))
				Debug.LogError($"CurrentState [{Key}] Already have Transition [{_transition.Key}]");
			else
			{
				transitions.Add(_transition);
				ResortTransition();
			}
		}

		public void EnterState(IState _preState)
		{
			tempPreState = _preState;
			OnEnter();
			interactable = true;
		}

		public void ExitState(IState _nextState)
		{
			interactable = false;
			tempNextState = _nextState;
			OnExit();
		}

		public void SetMachine(IFSM _machine)
		{
			machine = _machine;
		}

		virtual public void UpdateState(float _deltaTime)
		{
			if (interactable == false)
				return;
			if( (time += _deltaTime) > duration)
			{
				OnUpdate();
				//Do Transition Valid Check
				for (int index = 0; index < transitions.Count; index++)
				{
					if (!transitions[index].TransferValid())
						continue;
					else
					{
						//当前状态转换正在执行
						if(shifting == false)
							DealTransition(transitions[index]);
						break;
					}
				}
				//reset time
				time = 0;
			}
		}

		public FSMStateBase(string _key,IFSM _machine, float _duration = 0.02f)
		{
			this.stateKey = _key;
			this.duration = _duration;
			this.machine = _machine;
			transitions = new List<ITransition>();
		}
		virtual protected void ResortTransition()
		{
			//按照优先级顺序进行排序
			transitions.Sort((x, y) => y.Priority.CompareTo(x.Priority));
		}
		virtual protected void OnEnter()
		{
			Debug.Log($"CurrentState [{Key}]");
			//Do Setting 
			time = 0;
		}
		virtual protected void OnExit()
		{
			time = 0;
			tempPreState = null;
			tempNextState = null;
		}
		virtual protected void DealTransition(ITransition transition)
		{
			shifting = true;
			if (machine.CurState != transition.FromState)
				Debug.LogError("转移起始状态异常");
			else
			{
				machine.CurState.ExitState(transition.ToState);
				machine.SetState(transition.ToState);
				machine.CurState.EnterState(transition.FromState);
			}
			shifting = false;
			transition.OnCompleteCallBack(); 
		}
		virtual protected void OnUpdate()
		{
		 
		}

		protected string stateKey = "";
		//fixed time
		protected float duration = 0.02f;
		protected float time;
		protected IFSM machine;
		protected List<ITransition> transitions;
		//protected Dictionary<string, ITransition> transitionsDic;
		protected bool shifting = false;
		protected bool interactable = false;
		protected IState tempPreState;
		protected IState tempNextState;

	}
}